use crate::utils::ThreadSafePtr;
use crate::{thread_safe_ptr, unsafe_assign};
use lazy_static::lazy_static;
use std::cell::RefCell;
use std::fmt::{Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::sync::Mutex;
use std::time::Duration;
///一些常用的锁和多线程下锁的使用
/// 存在一个全局静态变量但是再rust语义中是不安全的，只能读
lazy_static! {
    static ref MSG: String = { "ONLY YOU".to_string() };// MSG is read only
}
/// 如果想对全局变量做更改必须使用Mutex处理，或者使用不安全的指针
lazy_static! {
    static ref WRITE_BOX: Mutex<String> = Mutex::new("is all right".to_string());// 有参safely changed it，but only one thread can own this at once
    static ref COSNT_STR : DropBox<String> = DropBox("what is this".to_string());
    static ref UNSAFE_WRITE_BOX: ThreadSafePtr<DropBox<String>> = ThreadSafePtr::capture(&COSNT_STR);
}
/// 如果想保障局部安全性，可以使用thread_local,由于所有的静态变量都不允许显示标注mut必须使用RefCell实现内部可变
thread_local! {
    static LOCAL_MSG : RefCell<usize> = RefCell::new(0);
}

struct DropBox<T>(T);

impl<T: Display> Display for DropBox<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl<T> Drop for DropBox<T> {
    fn drop(&mut self) {
        println!("!!!Drop Now!!!");
    }
}

//##################################################################################################//
/// 可见即使线程不安全依旧可以修改全局变量不会出现安全问题，rust的安全机制仅限于
#[test]
fn test_thread_unsafe_change() {
    println!("{}", *UNSAFE_WRITE_BOX);
    let mut thread_handle_poor = vec![];
    for x in 0..10 {
        thread_handle_poor.push(std::thread::spawn(move || {
            unsafe_assign!(**UNSAFE_WRITE_BOX, DropBox(format!("index is {}", x)));
            // std::thread::sleep(Duration::from_micros(20));
            println!("times:{}->info:{}", x, *UNSAFE_WRITE_BOX);
        }));
    }
    thread_handle_poor.into_iter().for_each(|each| {
        each.join().unwrap();
    })
}
//##################################################################################################//
///由于Mutex不提供多所有权机制，所以再多线程中使用Mutex可以使用Arc或者不安全的指针处理
#[test]
fn test_mutex() {
    thread_safe_ptr! {
        let safe_write_ptr = WRITE_BOX.deref();
    }
    let mut thread_vec = Vec::new();
    thread_vec.reserve(2 << 4);
    for x in 0..10 {
        thread_vec.push(std::thread::spawn(move || {
            let mut lock_guard = safe_write_ptr.lock().unwrap();
            *lock_guard = format!("each is {}", x);
            println!("{}", *lock_guard);
        }));
    }
    thread_vec.into_iter().for_each(|item| {
        item.join().unwrap();
    });
}

#[test]
fn test_thread_local() {
    let mut thread_vec = vec![];
    for x in 0..10 {
        thread_vec.push(std::thread::spawn(move || {
            LOCAL_MSG.with(|val| {
                println!("{}", val.borrow());
                *val.borrow_mut() += 1;
                println!("{}", val.borrow());
            });
        }));
    }
    thread_vec.into_iter().for_each(|item| {
        item.join().unwrap();
    });
}
